package org.apache.ibatis.ibator.generator.ibatis3.pagination.javamapper;

import java.util.Set;
import java.util.TreeSet;

import org.apache.ibatis.ibator.api.IntrospectedTable;
import org.apache.ibatis.ibator.api.dom.java.FullyQualifiedJavaType;
import org.apache.ibatis.ibator.api.dom.java.Interface;
import org.apache.ibatis.ibator.api.dom.java.JavaVisibility;
import org.apache.ibatis.ibator.api.dom.java.Method;
import org.apache.ibatis.ibator.api.dom.java.Parameter;
import org.apache.ibatis.ibator.config.IbatorContext;
import org.apache.ibatis.ibator.internal.util.messages.Messages;

public class JavaMapperPaginationGenerator {

    private Interface interfaze;
    private IntrospectedTable introspectedTable;
    private IbatorContext ibatorContext;

    public JavaMapperPaginationGenerator(Interface interfaze,
            IntrospectedTable introspectedTable, IbatorContext ibatorContext) {
        super();
        this.interfaze = interfaze;
        this.introspectedTable = introspectedTable;
        this.ibatorContext = ibatorContext;
    }

    public void generator() {
        if (introspectedTable.getRules().generateSelectByExampleWithBLOBs()) {
            generatorWithBLOBs();
        }
        if (introspectedTable.getRules().generateSelectByExampleWithoutBLOBs()) {
            generatorWithoutBLOBs();
        }
    }

    public void generatorWithBLOBs() {
        Set<FullyQualifiedJavaType> importedTypes = new TreeSet<FullyQualifiedJavaType>();
        FullyQualifiedJavaType type = new FullyQualifiedJavaType(
                "java.util.HashMap");
        importedTypes.add(type);
        importedTypes.add(FullyQualifiedJavaType.getNewListInstance());

        Method method = new Method();
        method.setVisibility(JavaVisibility.PUBLIC);

        FullyQualifiedJavaType returnType = FullyQualifiedJavaType
                .getNewListInstance();
        FullyQualifiedJavaType listType;
        if (introspectedTable.getRules().generateRecordWithBLOBsClass()) {
            listType = new FullyQualifiedJavaType(
                    introspectedTable.getRecordWithBLOBsType());
        } else {
            // the blob fields must be rolled up into the base class
            listType = new FullyQualifiedJavaType(
                    introspectedTable.getBaseRecordType());
        }

        importedTypes.add(listType);
        returnType.addTypeArgument(listType);
        method.setReturnType(returnType);

        if (ibatorContext.getSuppressTypeWarnings(introspectedTable)) {
            method.addSuppressTypeWarningsAnnotation();
        }

        method.setName(introspectedTable
                .getSelectByExampleWithBLOBsStatementId() + "Pagination");
        method.addParameter(new Parameter(type, "hashmap")); //$NON-NLS-1$

        ibatorContext.getCommentGenerator().addGeneralMethodComment(method,
                introspectedTable);

        if (ibatorContext.getPlugins()
                .daoSelectByExampleWithBLOBsMethodGenerated(method, interfaze,
                        introspectedTable)) {
            interfaze.addImportedTypes(importedTypes);
            interfaze.addMethod(method);
        }
    }

    public void generatorWithoutBLOBs() {
        Set<FullyQualifiedJavaType> importedTypes = new TreeSet<FullyQualifiedJavaType>();
        FullyQualifiedJavaType type = new FullyQualifiedJavaType(
                "java.util.HashMap");
        importedTypes.add(type);
        importedTypes.add(FullyQualifiedJavaType.getNewListInstance());

        Method method = new Method();
        method.setVisibility(JavaVisibility.PUBLIC);

        FullyQualifiedJavaType returnType = FullyQualifiedJavaType
                .getNewListInstance();
        FullyQualifiedJavaType listType;
        if (introspectedTable.getRules().generateBaseRecordClass()) {
            listType = new FullyQualifiedJavaType(
                    introspectedTable.getBaseRecordType());
        } else if (introspectedTable.getRules().generatePrimaryKeyClass()) {
            listType = new FullyQualifiedJavaType(
                    introspectedTable.getPrimaryKeyType());
        } else {
            throw new RuntimeException(Messages.getString("RuntimeError.12")); //$NON-NLS-1$
        }

        importedTypes.add(listType);
        returnType.addTypeArgument(listType);
        method.setReturnType(returnType);

        if (ibatorContext.getSuppressTypeWarnings(introspectedTable)) {
            method.addSuppressTypeWarningsAnnotation();
        }

        method.setName(introspectedTable.getSelectByExampleStatementId()
                + "Pagination");
        method.addParameter(new Parameter(type, "example")); //$NON-NLS-1$

        ibatorContext.getCommentGenerator().addGeneralMethodComment(method,
                introspectedTable);

        if (ibatorContext.getPlugins()
                .daoSelectByExampleWithoutBLOBsMethodGenerated(method,
                        interfaze, introspectedTable)) {
            interfaze.addImportedTypes(importedTypes);
            interfaze.addMethod(method);
        }
    }

}
